using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.ComponentModel;

namespace Omniture.API
{
	public enum TrackItemConstants
	{
		EVar,
		Prop,
		Event,
	}

	public abstract class TrackItemBase : ITrackItem
	{
		#region Class Members

		protected const string _def_name = "[New Object]";

		protected string _name = _def_name;
		protected string _alias = "";
		protected int _id = 0;
		protected string _description = "";
		protected TrackItemCollection _parent = null;

		#endregion

		#region Constructors

		internal TrackItemBase(TrackItemCollection parent, int id)
		{
			if (parent == null)
				throw new Exception("The parent must be set!");

			_parent = parent;
			_id = id;
		}

		#endregion

		#region Property Implementations

		public abstract TrackItemConstants ItemType { get; }

		[Browsable(false)]
		public TrackItemCollection ParentCollection
		{
			get { return _parent; }
		}

		[Browsable(true)]
		[Description("The name of this item.")]
		[Category("General")]
		public virtual string Name
		{
			get { return _name; }
			set
			{
				if (!ValidateName(value)) throw new Exception("The name is not valid!");
				if ((_parent != null) && (_parent.ParentItem != null))
				{
					if (!_parent.ParentItem.IsTrackItemUnique(value, this))
					{
						throw new Exception("The name is not unique!");
					}
				}
				_name = value;
			}
		}

		[Browsable(true)]
		[Description("The name used for library generation.")]
		[Category("General")]
		public virtual string Alias
		{
			get { return _alias; }
			set { _alias = value; }
		}

		[Browsable(true)]
		[Description("A description for this object.")]
		[Category("General")]
		public virtual string Description
		{
			get { return _description; }
			set { _description = value; }
		}

		[Browsable(false)]
		public virtual int Id
		{
			get { return _id; }
			set { _id = value; }
		}

		[Browsable(false)]
		public virtual string CodeName
		{
			get
			{
				string retval = this.Alias + "";
				if (retval == "") retval = this.Name + "";
				return CreateToken(retval);
			}
		}

		public virtual void LoadXml(XmlNode parentNode)
		{
			_name = XmlHelper.GetAttribute(parentNode, "Name", _name);
			_id = int.Parse(XmlHelper.GetAttribute(parentNode, "Id", _id.ToString()));
			_alias = XmlHelper.GetAttribute(parentNode, "Alias", _alias);
			_description = XmlHelper.GetAttribute(parentNode, "Description", _description);
		}

		public virtual void SaveXml(XmlNode parentNode)
		{
			XmlHelper.AddAttribute(parentNode, "Name", this.Name);
			XmlHelper.AddAttribute(parentNode, "Id", this.Id);
			XmlHelper.AddAttribute(parentNode, "Alias", this.Alias);
			XmlHelper.AddAttribute(parentNode, "Description", this.Description);
		}

		#endregion

		#region Methods

		private const string VALID_TOKEN_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_";
		public static bool ValidateName(string text)
		{
			if (text == _def_name) return false;
			return (text != null) && (text != "") && (text == CreateToken(text));
		}

		public static string CreateToken(string text)
		{
			if (text == null) return "";
			if (text.Length == 0) return "";

			string retval = "";
			foreach (char c in text)
			{
				if (VALID_TOKEN_CHARS.Contains(c.ToString().ToLower()))
					retval += c;
			}

			//Cannot start with a number
			if (string.IsNullOrEmpty(retval)) return "";
			if (('0' <= retval[0]) && (retval[0] <= '9')) retval = "T" + retval;
			return retval;
		}

		public override string ToString()
		{
			string retval = this.Name;
			if (this.Alias != "") retval += " (" + this.Alias + ")";
			return retval;
		}

		#endregion

	}
}